perm filename MTADDT.SAI[SS,SYS]1 blob sn#504391 filedate 1980-05-05 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00009 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	BEGIN "MTADDT"
C00003 00003	! MTC bit assignments and CONO procedures
C00007 00004	! MTS bit assignments and procedures
C00009 00005	! MTM bit assignments and procedures
C00012 00006	! Low level CONO, DATAO, CONI, DATAI routines
C00017 00007	! User interface routines: prompt, GetCmd
C00020 00008	! Execute a command string
C00027 00009	! The main loop
C00029 ENDMK
C⊗;
BEGIN "MTADDT"

REQUIRE "HEADER.SAI[LIB,ROB]" SOURCE_FILE;

DEFINE Bit(arg) = {(1 LSH (35-arg))};
DEFINE
  promptstr = {"*"},
  againchr = {"*"};

RECORD_CLASS cmd(
  STRING cmdstr;
  STRING oldstr;
  INTEGER rptarg);

INTEGER MTCStickyBits, Sleeptics;
! MTC bit assignments and CONO procedures;

DEFINE MTC = {'220};		comment MTC is device 220;

! Next are the CONI/CONO bit assignments.  The non-indented definitions
  are the bit position in the 36-bit word.  The sub-categories following
  are the meaning of the bits in those positions;

DEFINE
  RDFER = {Bit(18)},		comment False End of Record (CONI only);
  WTEWC = {Bit(19)},		comment Write Clock Enable (CONI only);
  SLICE = {Bit(20)},		comment Slice Level;
    SLICHI = {0},	comment Set high slice (normal);
    SLICLO = {1},	comment set low slice;
  PARITY = {Bit(21)},	comment Parity;
    PAREVN = {00},	comment set even parity;
    PARODD = {01},	comment set odd parity;
  DENSITY = {Bit(23)},	comment Density (2 bits wide);
    BPI200 = {00},	comment 200 BPI;
    BPI556 = {01},	comment 556 BPI;
    BPI800 = {02},	comment 800 BPI;
  MTCFUNC = {Bit(27)},	comment function code (4 bits wide);
    MTCNOP = {'00},	comment NO OPERATION;
    MTCREW = {'01},	comment REWIND;
    MTCWRT = {'02},	comment WRITE;
    MTCWEF = {'03},	comment WRITE END-OF-FILE;
    MTCRDC = {'04},	comment READ-COMPARE (NOT USED);
    MTCRED = {'05},	comment READ;
    MTCSFR = {'06},	comment SPACE FORWARD RECORD;
    MTCBSP = {'07},	comment BACKSPACE RECORD;
    MTCZZZ = {'10},	comment NO OPERATION (NOT USED);
    MTCRAU = {'11},	comment REWIND AND UNLOAD (SAME AS REWIND AT STANFORD);
    MTCRAR = {'12},	comment READ ACROSS RECORD (NOT USED);
    MTCW3I = {'13},	comment WRITE THREE INCHES (APPROX) OF MAG TAPE;
    MTCWLE = {'14},	comment WRITE WITH LONG EOR (NOT USED);
    MTCRDB = {'15},	comment READ BACKWARD (NOT USED);
    MTCSFF = {'16},	comment SPACE FORWARD FILE;
    MTCBSF = {'17},	comment BACKSPACE FILE;
  POOL = {Bit(28)},		comment Hold (don't pool) after completion;
  UNITNUM = {Bit(31)},		comment Software Unit number (3 bits wise);
  EORDISABLE = {Bit(32)},	comment maintenance only;
  MTCPIA = {Bit(35)},		comment PIA assignment (3 bits wide);
   PIAOFF = {'0},	comment Turn off the PIA;
   PIAON = {'4};	comment Turn on the PIA;

! MTS bit assignments and procedures;

COMMENT ⊗

Device 224	MTS
Bit	CONO 		CONI
18	INT CLR		CS ILC		Initial-Clear / Illegal command
19	unused		MD DCS		Motion Stop delay in progress
20	LIE		MD LIF		Load point interrupt Enable/Bit
21	XNE		CS XNC		Transfer next command Enable/Bit
22			T Rewinding
23			T End Point
24			T Load Point
25			TLR Last	Last operation was a Write
26			TFR A/B work	Local ∨ other controller is using this unit
27			EFF		End of File Flag
28			T Write Lock
29			RD MIS		Missed character
30			RD RCE		Read compare error
31			RD LPE		Long. Parity Error
32			PER		Lat. Parity Error
33	EFE		MD ERF		End of Record Flag Enable/Bit
34	Prog JNU	ST Ready	Tape Unit Ready
35	ICE		MD ICR		Interface & Control Enable/Ready

⊗;

DEFINE MTS = {'224};		comment MTS is device 224;

DEFINE
  MTSCLR = {Bit(18)};
! MTM bit assignments and procedures;

COMMENT ⊗

Device 230	MTM
Note: All CONO bit are ignored, however the CONO itself causes a programmed
CHP pulse to occur.

Bit			CONI
18			CS UPS		Up to speed
19			CS RIP		Record in Progress
20			CS ERM		End of record motion delay in progress
21			CS CON		Motion Continue Selected
22			CS CHF		Command Hold buffer Full
23			CS UNS		Unit selected new command
24			CM Function-8	Final function register
25			CM Function-4
26			CM Function-2
27			CM Function-1
28			CM Unit-4	Final Unit register
29			CM Unit-2
30			CM Unit-1
31			MD MOD		
32			RD FCD
33			RD ERD		Read End of Record delay
34			RD MCD
35			WT EWD		End of record Write delay

⊗;
! Low level CONO, DATAO, CONI, DATAI routines;

! These routines should be in a .REL file library on [LIB,ROB];

DEFINE CONO = {'700200000000};
DEFINE CONI = {'700240000000};
DEFINE DATAO = {'700140000000};
DEFINE DATAI = {'700040000000};
DEFINE EIOTM = {'047000400005};
DEFINE POINTC(bytsiz,addr,lowbit) = {((bytsiz LSH 24)+((35-lowbit) LSH 30)+addr)};

PROCEDURE ConoDev(
  INTEGER dev,conoword);
  Q⊂ "ConoDev"
  LABEL $liotm;
  ! This obtuse bit of start code fabricates a CONO instruction in AC 2,
    depositing the device code and cono data word in the proper fields.
    It then enters IOT user mode, XCTs the CONO, and gets out of IOT user
    mode;

	MOVE 2,[CONO];		! start with a naked CONO
		! ac2 now = CONO nil,0;
	MOVE 1,dev;
	LSH 1,-2;		! The device code is really only 7 bits wide (not 9);
	DPB 1,[POINTC(7,2,9)];	! deposit the device code;
		! ac2 now = CONO DEV,0;
	MOVE 1,conoword;
	DPB 1,[POINTC(18,2,35)];! deposit the data;
		! ac2 now = CONO DEV,CONOWORD;
	EIOTM;			! enter the dangerous land...;
	XCT 2;			! do the instruction;
		! the next two instructions get us out of IOT user mode by
		! turning off the PC flags.  I would have said JRST 2,@[.+1],
		! but the silly SAIL assembler doesnt do address arithmetic;
	MOVEI 3,$liotm;
	JRST 2,@3;
$liotm:

  ⊃ "ConoDev";

INTEGER PROCEDURE ConiDev(
  INTEGER dev);
  Q⊂ "ConiDev"
  LABEL $liotm;
	MOVE 2,[CONI];		! CONI nil,0;
	MOVE 1,dev;
	LSH 1,-2;		! The device code is really only 7 bits wide (not 9);
	DPB 1,[POINTC(7,2,9)];	! CONI DEV,0;
	HRRI 2,1;		! CONI DEV,1	ie, return results in AC 1;
	EIOTM;			! enter the dangerous land...;
	XCT 2;			! do the instruction;
	MOVEI 3,$liotm;		! Get out of IOT user mode (the hard way);
	JRST 2,@3;
$liotm:
  ⊃ "ConiDev";

PROCEDURE DataoDev(
  INTEGER dev,dataoword);
  Q⊂ "DataoDev"
  LABEL $liotm;
	MOVE 2,[DATAO];		! DATAO nil,0;
	MOVE 1,dev;
	LSH 1,-2;		! The device code is really only 7 bits wide (not 9);
	DPB 1,[POINTC(7,2,9)];	! DATAO DEV,0;
	HRRI 2,1;		! DATAO DEV,1	ie, AC 1 will have the data;
	MOVE 1,dataoword;	! put the data in AC1
	EIOTM;			! enter the dangerous land...;
	XCT 2;			! do the instruction;
	MOVEI 3,$liotm;		! Get out of IOT user mode;
	JRST 2,@3;
$liotm:
  ⊃ "DataoDev";

INTEGER PROCEDURE DataiDev(
  INTEGER dev);
  Q⊂ "DataiDev"
  LABEL $liotm;
	MOVE 2,[DATAI];		! DATAI nil,0;
	MOVE 1,dev;
	LSH 1,-2;		! The device code is really only 7 bits wide (not 9);
	DPB 1,[POINTC(7,2,9)];	! DATAI DEV,0;
	HRRI 2,1;		! DATAI DEV,1	ie, return results in AC 1;
	EIOTM;			! enter the dangerous land...;
	XCT 2;			! do the instruction;
	MOVEI 3,$liotm;		! Get out of IOT user mode (the hard way);
	JRST 2,@3;
$liotm:
  ⊃ "DataiDev";
! User interface routines: prompt, GetCmd;

PROCEDURE Prompt; ⊂ PRINT(promptstr) ⊃;

! PROCEDURE MakeUpper(INTEGER chr);! RETURN(IF ("a"≤chr≤"z") (chr-("a"-"A")) ELSE chr);

INTEGER PROCEDURE MakeUpper(INTEGER chr);
  IF ("a"≤chr≤"z")
    THEN RETURN(chr-("a"-"A"))
    ELSE RETURN(chr);

PROCEDURE GetCmd(
  RECORD_POINTER(cmd) C);
  ⊂ "GetCmd"
  STRING str;
  INTEGER brk;
  str ← INCHWL;
  IF ("0" ≤ str ≤ "9")
    THEN
      ⊂ "Got a numeric argument"
      cmd:rptarg[C] ← CVD(str);
      WHILE ("0" ≤ str ≤ "9") DO str ← str[2 TO ∞];
      ⊃ "Got a numeric argument"
    ELSE
      ⊂ "No numeric argument"
      cmd:rptarg[C] ← 1;	! no numeric arg defaults to 1;
      ⊃ "No numeric argument";
  IF (str ≠ againchr) THEN cmd:cmdstr[C] ← str;
  ⊃ "GetCmd";


! Execute a command string;

PROCEDURE Execute(
  RECORD_POINTER(cmd) C);
  ⊂ "Execute"
  STRING str;
  INTEGER ChrPtr;		! points to current character within string;
  str ← cmd:cmdstr[C];
  FOR ChrPtr ← 1 THRU LENGTH(str) DO
    ⊂ "Do a command"
    CASE MakeUpper(str[ChrPtr FOR 1]) OF
      ⊂ "command case"
      ["?"]
	⊂ "list commands"
	PRINT("
This is a simple tape drive diagnostic which does direct IO instructions to the
tape controller.  At the ",promptstr," prompt, type a string of commands. If you
precede the string with a number, the sequence will be repeated that many times.
For example, ""*99iesss"" will do the sequence initial-clear, write end-of-file,
and sleep for 50 milliseconds 99 times.

Valid commands are:
?	type this list			(does it only once per loop)
C	read-compare
D	set the density			(does it only once per loop)
E	write an end-of-file mark
I	execute an initial-clear
N	no operation
Q	quit and return to the monitor
R	read the tape
S	sleep for the time specified by last T command
T	set number of milliseconds to sleep (to nearest 1/60 second)
W	write
←	rewind
>	space forward record
<	backspace record
≥	space forward file
≤	backspace file
∃	write three inches (approx) of mag tape
");

	str ← str[1 TO ChrPtr-1] & str[ChrPtr+1 TO ∞]; ! remove from list;
	⊃ "list commands";
      ["C"]
	⊂ "rdcompare"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCRDC));
	⊃ "rdcompare";
      ["D"]
	⊂ "Set Density"
	STRING Dstr; INTEGER brk,Dens;
	PRINT("Density (0 for 220, 1 for 550, 2 for 800): ");
	Dstr ← INCHWL;
        CASE Dens ← INTSCAN(Dstr,brk) OF
	  ⊂ "Density case"
	  [0] print("Density = 200 bpi.",↓);
	  [1] print("Density = 550 bpi.",↓);
	  [2] print("Density = 800 bpi.",↓);
	  ELSE print("Unknown density specification.",↓)
	  ⊃ "Density case";
	IF (0≤Dens≤2) THEN 
	  MTCStickybits ← MTCStickyBits LAND (LNOT 3*DENSITY) + Dens*Density;
	str ← str[1 TO ChrPtr-1] & str[ChrPtr+1 TO ∞]; ! remove from list;
	⊃ "Set Density";
      ["E"]
	⊂ "Write End-of-File"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCWEF));
	⊃ "Write End-of-File";
      ["I"] 
	⊂ "Initial-clear"
	ConoDev(MTS,MTSCLR);
        ⊃ "Initial-clear";
      ["N"]
	⊂ "No-op"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCNOP));
	⊃ "No-op";
      ["Q"]
	⊂ "Quit"
	ConoDev(MTC,MTCPIA * PIAON);	comment Restore the PIA;
	cmd:rptarg[C] ← 0;
	⊃ "Quit";
      ["R"]
	⊂ "Read The Tape Dammit"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCRED));
	⊃ "Read The Tape Dammit";
      ["S"]
	⊂ "Sleep"
	INTEGER I;
	FOR I ← 0 THRU Sleeptics DO
	  Q⊂ "Sleep for a tic"
	  DEFINE sleep = {'047000000031};
	  MOVEI 1,0	;
	  SLEEP	1,	;
	  ⊃ "Sleep for a tic";
	⊃ "Sleep";
      ["T"]
	⊂ "TimeSet"
	STRING Tstr; INTEGER brk, ttics;
	PRINT("How many milliseconds per S command: "); Tstr ← INCHWL;
	ttics ← (60 * INTSCAN(Tstr,brk))/1000;
	IF ttics=0 THEN PRINT("(no change)",↓) ELSE Sleeptics ← ttics;
	PRINT("S commands now sleep for ",sleeptics*(1000/60)," milliseconds",↓);
	str ← str[1 TO ChrPtr-1] & str[ChrPtr+1 TO ∞]; ! remove from list;
	⊃ "TimeSet";
      ["W"]
	⊂ "MTCWRT"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCWRT));
	⊃ "MTCWRT";
      ["←"]
	⊂ "rewind"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCREW));
	⊃ "rewind";
      [">"]
	⊂ "MTCSFR"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCSFR));
	⊃ "MTCSFR";
      ["<"]
	⊂ "MTCBSP"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCBSP));
	⊃ "MTCBSP";
      ["≥"]
	⊂ "MTCSFF"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCSFF));
	⊃ "MTCSFF";
      ["≤"]
	⊂ "MTCBSF"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCBSF));
	⊃ "MTCBSF";
      ["∃"]
	⊂ "MTCW3I"
	ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCW3I));
	⊃ "MTCW3I";
      ELSE PRINT("Unrecognized command character ",str[ChrPtr FOR 1],↓)
      ⊃ "command case"
    ⊃ "Do a command";
! D$PRINT(<"Command string = ",str,↓>);
  cmd:cmdstr[C] ← str;	! update the command string;
  ⊃ "Execute";
! The main loop;

RECORD_POINTER(cmd) C;
C ← NEW_RECORD(cmd);
cmd:cmdstr[C] ← "";
cmd:oldstr[C] ← "";
cmd:rptarg[C] ← 0;

SleepTics ← 1;	! Default to 1 tic;
MTCStickyBits ← (PARITY * PARODD) + (DENSITY * BPI800) + (MTCPIA * PIAOFF);
! set odd parity, density at 800bpi, PIA turned off;

PRINT("Type ""?"" for help.",↓);

DO
  ⊂ "main" ! The main command loop;
  INTEGER I;
  prompt;
  GetCmd(C);
  IF cmd:rptarg[C] > 0 THEN FOR I ← 1 THRU cmd:rptarg[C] DO Execute(C);
  ⊃ "main"
  UNTIL cmd:rptarg[C] = 0;
  

print("So long.",↓);
quit;

END "MTADDT";